package com.imooc.controller.center;

import com.imooc.BO.center.CenterUserBO;
import com.imooc.controller.BaseController;
import com.imooc.pojo.Users;
import com.imooc.resouce.FileUpload;
import com.imooc.service.center.CenterUserService;
import com.imooc.utils.CookieUtils;
import com.imooc.utils.DateUtil;
import com.imooc.utils.IMOOCJSONResult;
import com.imooc.utils.JsonUtils;
import com.imooc.vo.UsersVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author gcq
 * @Create 2022-01-25
 */
@Api(value = "用户信息接口", tags = {"用户信息相关接口"})
@RestController
@RequestMapping("userInfo")
public class CenterUserController extends BaseController {

    @Autowired
    CenterUserService centerUserService;

    @Autowired
    FileUpload fileUpload;

    /**
     * 考虑问题
     *      1、上传文件的类型 前端做了验证，后端也需要做验证，防止黑客攻击 防止上传可执行的文件 防止上传.sh .php
     * @param userId
     * @param file
     * @param request
     * @param response
     * @return
     */
    @ApiOperation(value = "用户头像上传", notes = "用户头像上传", httpMethod = "POST")
    @PostMapping("uploadFace")
    public IMOOCJSONResult userInfo(
            @ApiParam(name = "userId", value = "用户Id", required = true)
            @RequestParam String userId,
            @ApiParam(name = "file", value = "用户头像", required = true)
                    MultipartFile file,
                    HttpServletRequest request,
                    HttpServletResponse response) {
        // 上传路径
        String fileSpace = fileUpload.getImageUserFaceLocation();
        // 区分不同用户上传
        String uploadPathPreFix = File.separator + userId;
        // 文件名称
        String fileName = file.getOriginalFilename();

        if (file != null) {
            FileOutputStream fileOutputStream = null;
            try {
                if (StringUtils.isNotBlank(fileName)) {
                    // 文件拆分
                    String[] fileNameArr = fileName.split("\\.");
                    // 获取文件后缀
                    String suffix = fileNameArr[fileNameArr.length - 1];

                    // 限制上传格式
                    if(!suffix.equalsIgnoreCase("png") &&
                       !suffix.equalsIgnoreCase("jpg") &&
                       !suffix.equalsIgnoreCase("jpeg")) {
                        return IMOOCJSONResult.ok("图片格式不正确");
                    }

                    // 文件名称重组
                    String newFileName = "face-" + userId + "." + suffix;

                    // 上传文件最终地址
                    String finalFacePath = fileSpace + uploadPathPreFix + File.separator + newFileName;
                    // 用于提供给web访问地址
                    uploadPathPreFix += ("/" + newFileName);

                    File outFile = new File(finalFacePath);
                    if (outFile.getParentFile() != null) {
                        // 创建父文件目录
                        outFile.getParentFile().mkdirs();
                    }
                    // 文件保存到目录中
                    fileOutputStream = new FileOutputStream(outFile);
                    InputStream inputStream = file.getInputStream();
                    // IOUtils 将输入流拷贝到对应流中
                    IOUtils.copy(inputStream, fileOutputStream);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if(fileOutputStream != null) {
                        fileOutputStream.flush();
                        fileOutputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        else {
            return IMOOCJSONResult.errorMsg("文件不能为空");
        }
        String imageServerUrl = fileUpload.getImageServerUrl();
        // 由于浏览器中有缓存，更换图片后不会刷新，加上时间戳自动刷新
        String finalUserFaceUrl = imageServerUrl + uploadPathPreFix + "?t=" + DateUtil.getCurrentDateString(DateUtil.DATE_PATTERN);

        // 更新用户头像地址
        Users users = centerUserService.updateUserFace(userId, finalUserFaceUrl);

        this.setNullProperty(users);

        UsersVO usersVO = convertUserVO(users);

        CookieUtils.setCookie(request, response, "user", JsonUtils.objectToJson(usersVO), true);

        return IMOOCJSONResult.ok();
    }

    /**
     * 使用注解进行验证参数
     *
     * @param userId
     * @param centerUserBo
     * @param result
     * @param request
     * @param response
     * @return
     */
    @ApiOperation(value = "修改用户信息", notes = "修改用户信息", httpMethod = "POST")
    @PostMapping("update")
    public IMOOCJSONResult userInfo(
            @ApiParam(name = "userId", value = "用户Id", required = true)
            @RequestParam String userId,
            @RequestBody @Valid CenterUserBO centerUserBo,
            BindingResult result,
            HttpServletRequest request,
            HttpServletResponse response) {

        if (result.hasErrors()) {
            Map<String, String> errorsMap = this.getErrors(result);
            return IMOOCJSONResult.errorMap(errorsMap);
        }

        Users users = centerUserService.updateUserInfo(userId, centerUserBo);

        this.setNullProperty(users);

        CookieUtils.setCookie(request, response, "user", JsonUtils.objectToJson(users), true);

        // 后续增加令牌token 整合会话redis 分布式会话
        convertUserVO(users);
        return IMOOCJSONResult.ok(users);
    }

    /**
     * 获取 BindingResult 中的错误信息
     *
     * @param result
     * @return
     */
    private Map<String, String> getErrors(BindingResult result) {
        Map<String, String> map = new HashMap<>();
        List<FieldError> fieldErrors = result.getFieldErrors();
        for (FieldError error : fieldErrors) {
            String field = error.getField();
            String message = error.getDefaultMessage();
            map.put(field, message);
        }
        return map;
    }

    private void setNullProperty(Users users) {
        users.setPassword(null);
        users.setMobile(null);
        users.setEmail(null);
//        users.setId(null);
        users.setCreatedTime(null);
        users.setUpdatedTime(null);
        users.setBirthday(null);
    }
}